package cn.com.thinker.tools;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Properties;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
 * 
 * @author nibili 2015年4月16日
 * 
 */
public class VelocityUtils {
	
	private static Logger logger = LoggerFactory.getLogger(VelocityUtils.class);
	
	// 配置使用classloader加载资源
    public static final String VM_LOADPATH_KEY = "file.resource.loader.class";
    public static final String VM_LOADPATH_VALUE = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
    public static final String UTF8 = Charset.forName("UTF-8").name();
	
	public static VelocityUtils velocityUtils = new VelocityUtils();
	private VelocityUtils(){
		if (engine == null) {
            Properties p = new Properties();
            p.setProperty(Velocity.ENCODING_DEFAULT, UTF8);
            p.setProperty(Velocity.INPUT_ENCODING, UTF8);
            p.setProperty(Velocity.OUTPUT_ENCODING, UTF8);
            p.setProperty("file.resource.loader.unicode", "true");
            engine = new VelocityEngine(p);
        }
	}
	
	public static VelocityUtils instance(){
		return velocityUtils;
	}
	
	 /**
     * velocity引擎
     */
    private VelocityEngine engine;

    /**
     * 方式一：加载classpath目录下的vm文件
     Properties p = new Properties();
     p.put("file.resource.loader.class",
     "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
     Velocity.init(p);
     ...
     Velocity.getTemplate(templateFile);


     方式二：根据绝对路径加载，vm文件置于硬盘某分区中，如：d://tree.vm
     Properties p = new Properties();
     p.setProperty("resource.loader", "file");
     p.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, "");
     Velocity.init(p);
     ...
     Velocity.getTemplate("tree.vm");




     方式三：使用文本文件，如：velocity.properties，配置如下：
     input.encoding = UTF-8
     file.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

     再利用如下方式进行加载
     Properties p = new Properties();
     p.load(this.getClass().getResourceAsStream("/velocity.properties"));
     Velocity.init(p);

     方法四：jar包加载

     //设置velocity资源加载方式为file时的处理类
     properties.setProperty("jar.resource.loader.class", "org.apache.velocity.runtime.resource.loader.JarResourceLoader");
     //设置jar包所在的位置
     properties.setProperty("jar.resource.loader.path", "jar:file:WebRoot/WEB-INF/lib/vm.jar");

     */
    /**
     * 将模板转化成文件
     * @param context
     * @param templatePath 模板绝对路径
     * @param outputFile
     */
    public void absPathToFile(VelocityContext context, String templatePath, String outputFile){
        VelocityEngine velocity = this.engine;
        velocity.setProperty("resource.loader", "file");
        velocity.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, "");
        velocity.clearProperty(VM_LOADPATH_KEY);
        vmToFile(context,templatePath,outputFile,velocity);
    }

    /**
     * 将模板转化成文件
     * @param context
     * @param templatePath 模板classpath路径
     * @param outputFile
     */
    public void classPathToFile(VelocityContext context, String templatePath, String outputFile){
        VelocityEngine velocity = this.engine;
        velocity.setProperty(VM_LOADPATH_KEY, VM_LOADPATH_VALUE);
        velocity.clearProperty("resource.loader");
        velocity.clearProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH);
        vmToFile(context,templatePath,outputFile,velocity);
    }

	 /**
     * 将模板转化成为文件
     *
     * @param context      内容对象
     * @param templatePath 模板文件
     * @param outputFile   文件生成的目录
     */
    private void vmToFile(VelocityContext context, String templatePath, String outputFile,VelocityEngine velocity)  {
        if (StringUtils.isEmpty(templatePath)) {
            return;
        }

        Template template = velocity.getTemplate(templatePath, UTF8);
        File file = new File(outputFile);
        if (!file.getParentFile().exists()) {
            // 如果文件所在的目录不存在，则创建目录
            if (!file.getParentFile().mkdirs()) {
                logger.debug("创建文件所在的目录失败!");
                return;
            }
        }
        FileOutputStream fos;
        BufferedWriter writer = null;
		try {
			fos = new FileOutputStream(outputFile);
			writer = new BufferedWriter(new OutputStreamWriter(fos, UTF8));
	        template.merge(context, writer);
		} catch (FileNotFoundException | UnsupportedEncodingException e) {
			e.printStackTrace();
		}finally {
			if(writer!=null)
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
        logger.debug("模板:" + templatePath + ";  文件:" + outputFile);
    }

    /**
     * 设置模版引擎，主要指向获取模版路径
     */
//    private VelocityEngine getVelocityEngine() {
//        if (engine == null) {
//            Properties p = new Properties();
//            p.setProperty(ConstVal.VM_LOADPATH_KEY, ConstVal.VM_LOADPATH_VALUE);
//            p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
//            p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
//            p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
//            p.setProperty(Velocity.OUTPUT_ENCODING, ConstVal.UTF8);
//            p.setProperty("file.resource.loader.unicode", "true");
//            engine = new VelocityEngine(p);
//        }
//        return engine;
//    }
}
